﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	EntityList.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace Smart.Common.Entities
{
	/// <summary>
	/// Entity List collection
	/// </summary>
	[DebuggerDisplay("EntityList Name={Meta.Name}")]
	[DebuggerStepThrough]
	public class EntityList<TEntityType> : List<TEntityType>, IEntityList<TEntityType>
		where TEntityType : Entity
	{
		/// <summary>
		/// Fields metadata
		/// </summary>
		public MetaFields Meta { get; protected set; }

		/// <summary>
		/// List service
		/// </summary>
		public IListService<TEntityType> Service { get; protected set; }

		/// <summary>
		/// Entity List collection
		/// </summary>
		public EntityList(MetaFields meta, IListService<TEntityType> list)
		{
			Meta = meta;
			Service = list;
		}

		public virtual IEntityList<TEntityType> CloneForCache()
		{
			var res = new EntityList<TEntityType>(null, null);

			res.AddRange(this.Select(entity => (TEntityType)entity.Clone()));

			res.ClearChildrenItem();
			res.SetChildrenList();

			return res;
		}

		public virtual void CloneFromCache(IEntityList<TEntityType> cache)
		{
			AddRange(cache.Select(entity => (TEntityType)entity.Clone()));

			SetChildrenList();
		}

		protected virtual void SetChildrenList()
		{
			ForEach(entity => entity.List = (IEntityList)this);
		}

		protected virtual void ClearChildrenItem()
		{
			ForEach(entity => entity.Source = null);
		}

		/// <summary>
		/// Find entity in list by <paramref name="id"/>
		/// </summary>
		public virtual TEntityType FindById(Identifier id)
		{
			return Find(entity => object.Equals(entity.ID, id));
		}

		/// <summary>
		/// Create entity
		/// </summary>
		public virtual TEntityType Create(string entityName)
		{
			var entity = Service.CreateEntity(entityName, this);

			return
				entity != null && Service.FillEntity(entity)
					? entity
					: null;
		}

		/// <summary>
		/// Create entity
		/// </summary>
		public virtual TEntityType Create(Type entityType)
		{
			var entity = Service.CreateEntity(entityType, this);

			return
				entity != null && Service.FillEntity(entity)
					? entity
					: null;
		}

		/// <summary>
		/// Create entity
		/// </summary>
		public virtual TEntityType Create()
		{
			var entity = Service.CreateEntity(this);

			return
				entity != null && Service.FillEntity(entity)
					? entity
					: null;
		}

		/// <summary>
		/// Load entity
		/// </summary>
		public bool Load(TEntityType entity)
		{
			return Service.LoadEntity(entity);
		}

		/// <summary>
		/// Load entity source
		/// </summary>
		public object LoadSource(TEntityType entity)
		{
			return Service.LoadEntitySource(entity);
		}

		/// <summary>
		/// Save entity
		/// </summary>
		public bool Save(TEntityType entity)
		{
			return Service.SaveEntity(entity);
		}

		/// <summary>
		/// Recycle entity
		/// </summary>
		public bool Recycle(TEntityType entity)
		{
			return Service.RecycleEntity(entity);
		}

		/// <summary>
		/// Reload entity
		/// </summary>
		public bool Reload(TEntityType entity)
		{
			return Service.LoadEntity(entity);
		}

		#region IEntityList

		/// <summary>
		/// Load entity
		/// </summary>
		public bool Load(Entity entity)
		{
			return Service.LoadEntity((TEntityType)entity);
		}

		/// <summary>
		/// Load entity source
		/// </summary>
		public object LoadSource(Entity entity)
		{
			return Service.LoadEntitySource((TEntityType)entity);
		}

		/// <summary>
		/// Save entity
		/// </summary>
		public bool Save(Entity entity)
		{
			return Service.SaveEntity((TEntityType)entity);
		}

		/// <summary>
		/// Recycle entity
		/// </summary>
		public bool Recycle(Entity entity)
		{
			var item = entity.Source;

			return
				item == null
					? Service.RecycleEntity((TEntityType)entity)
					: Service.RecycleEntity((TEntityType)entity, item);
		}

		/// <summary>
		/// Reload entity
		/// </summary>
		public bool Reload(Entity entity)
		{
			return Service.LoadEntity((TEntityType)entity);
		}

		#endregion
	}
}